package main

import (
	"fmt"
)

// 切片：底层也是数组，可以动态改变长度：var name []type 或 var name []type = make([]type, len)
/**
0、每一个切片引用了一个底层数组
1、切片本身是不存储数据的，都是其底层的数组存储，所以修改切片也就是修改这个数组中的数据
2、切片容量：为当前数组最大容量<=长度时候，以*2的速度扩容
3、切片一旦扩容，就是重新指向一个新的底层数组
*/

func main() {
	// 一、基础
	var a []int     // 声明int类型切片
	var b = []int{} // 声明并且初始化

	if a == nil {
		fmt.Println("a是一个nil")
	}
	fmt.Println(a, len(a), cap(a))

	if b == nil {
		fmt.Println("b是一个nil")
	}
	fmt.Println(b, len(b), cap(b))

	// 二、append
	var myLst = []string{"上海", "北京", "深圳"}
	fmt.Println("----- 追加元素前 -----")
	fmt.Println("before myLst len: ", len(myLst)) // myLst len:  3
	fmt.Println("before myLst cap: ", cap(myLst)) // myLst cap:  3

	// 三、长度、容量
	myLst = append(myLst, "天津")
	fmt.Println("myLst: ", myLst) // myLst:  [上海 北京 深圳 天津]
	fmt.Println("----- 追加元素后 -----")
	fmt.Println("after myLst len: ", len(myLst)) // myLst len:  4
	fmt.Println("after myLst cap: ", cap(myLst)) // myLst cap:  6

	// 四、验证容量：是否为当前数组最大容量<=长度时候，是否以*2的速度扩容
	var nums = []int{}
	for i := 0; i <= 5; i++ {
		nums = append(nums, i)
		fmt.Println("cap: ", cap(nums))
	}

	// 如果从0个元素开始切片，则:左边可以省略
	// 如果从最后一个元素截取，则:右边可以省略
	var nus = []int{1, 2, 3, 4, 5, 6}
	fmt.Println(nus[:2]) // [1 2]
	fmt.Println(nus[5:]) // [6]

	// 五、make ---> 在创建空切片时候明确指定切片的容量大小
	// 创建一个当前容量为200、长度为0的空切片
	str2 := make([]string, 0, 200)
	fmt.Println("str2: ", len(str2), cap(str2)) // str2:  0 200

	// 六、copy
	// 如果想让切片完全独立与数组，可以使用copy()函数实现
	// go语言中的copy相当于python中的深拷贝(数据不共享)
	var names = [5]string{"北京", "上海", "深圳", "苏州", "杭州"}
	var namesCopy = make([]string, len(names))
	copy(namesCopy, names[:])
	namesCopy[0] = "重庆"

	fmt.Println("names: ", names)         // [北京 上海 深圳 苏州 杭州]
	fmt.Println("namesCopy: ", namesCopy) // [重庆 上海 深圳 苏州 杭州]
}
